package nanzhuli.user.svc.controller;

import com.alibaba.fastjson.JSONObject;
import com.monitorjbl.xlsx.StreamingReader;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import nanzhuli.user.svc.enums.CheckInEnum;
import nanzhuli.user.svc.exception.ParamException;
import nanzhuli.user.svc.exception.ServiceException;
import nanzhuli.user.svc.model.entity.StaffBonus;
import nanzhuli.user.svc.model.param.CheckInInfo;
import nanzhuli.user.svc.model.param.CheckInTime;
import nanzhuli.user.svc.model.resp.base.GenericDataResponse;
import nanzhuli.user.svc.model.resp.excel.OriginalRecord;
import nanzhuli.user.svc.service.FileService;
import nanzhuli.user.svc.util.ImportExcelUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author luoqiang
 * @description 文件上传/下载/解析
 * @date 2020/10/16
 */
@Api(value  = "文件上传/下载/解析", tags = "FileController")
@RestController
@RequestMapping("/api/v1")
@Slf4j
public class FileController {

    @Resource
    FileService fileService;

    @PostMapping("/cal_meal_subsidy")
    public void calMealSubsidy(MultipartFile file)  {
        try{
            parseExcelForGetMap(file);
        }catch (Exception e){
            log.error("计算员工餐补失败,原因:{}", e.getMessage(), e);
            throw new ServiceException("计算员工餐补失败");
        }
    }

    private void parseExcelForGetMap(MultipartFile file) {
        // 根据文件名获取月份名称信息  考勤统计-202009.xls
        String originalFilename = file.getOriginalFilename();
        log.info("originalFilename={}",originalFilename);
        String month = originalFilename.substring(originalFilename.indexOf("-")+1, originalFilename.indexOf("."));   //入库用
        Map<String,List> forAllListMap = new HashMap();  //人员出勤信息列表
        Map<String,Integer> lateMap = new HashMap(); //人员迟到次数统计
        List<StaffBonus> staffBonusList = new ArrayList();   //统计数据

        BufferedInputStream in = null;
        Workbook wk = null;
        try {
            in = (BufferedInputStream) file.getInputStream();
            wk = StreamingReader.builder()
                    .rowCacheSize(100)  //缓存到内存中的行数，默认是10
                    .bufferSize(4096)  //读取资源时，缓存到内存的字节大小，默认是1024
                    .open(in);  //打开资源，必须，可以是InputStream或者是File，注意：只能打开XLSX格式的文件
            Sheet sheet = wk.getSheetAt(0);
            for (Row row : sheet) {
                int rowNum = row.getRowNum();
                if(rowNum < 3){   //去除前三行
                    continue;
                }
                String attendanceGroup = null; // 考勤组
                String department = null; // 部门
                String position = null; //职位
                String name = null;
                String workDate = null; //考勤日期  20-09-01 星期二
                String workTime = null;   //考勤时间 2020-09-01 08:30
                String inTime = null;   //打卡时间 2020-09-01 08:47
                String recordResult = null;    //打卡结果  迟到
                try {
                    name = row.getCell(0).getStringCellValue();
                    attendanceGroup = row.getCell(1).getStringCellValue();
                    department = row.getCell(2).getStringCellValue();
                    position = row.getCell(4).getStringCellValue();
                    workDate = row.getCell(6).getStringCellValue();
                    workTime = row.getCell(7).getStringCellValue();
                    inTime =  row.getCell(8).getStringCellValue();
                    recordResult = row.getCell(9).getStringCellValue();
                //    if (!"北京橙子柚礼科技".equals(attendanceGroup) && !"北京公司".equals(attendanceGroup) ){
                //        continue;
                //    }
                    if (recordResult.contains("打卡无效")){
                        continue;
                    }
                    if (recordResult.contains("迟到")){
                        if(!lateMap.containsKey(name) ){
                            lateMap.put(name,1);
                        }else{
                            lateMap.put(name,lateMap.get(name)+1);
                        }
                    }

                    String key = name ;  //张三
                    Map<String,Object> people = new HashMap();
                    List<Map> popleList = new ArrayList<>();
                    List list = new ArrayList();
                    if (!forAllListMap.containsKey(name)){
                        if (workTime.substring(11,13).compareTo("12") <= 0 ){
                            list.add(0,inTime);
                        }
                        if (workTime.substring(11,13).compareTo("12") > 1){
                            list.add(0,null);
                            list.add(1,inTime);
                        }
                        people.put(workDate,list);
                        popleList.add(people);
                        forAllListMap.put(key,popleList);
                    }else{
                        boolean flag = false;
                        for (Object map : forAllListMap.get(name)){
                            if (map instanceof Map){
                                if (((Map) map).get(workDate)!=null){
                                    flag = true;
                                    if (workTime.substring(11,13).compareTo("12") <= 0 ){
                                        if (((Map) map).get(workDate) instanceof List){
                                            ((List) ((Map) map).get(workDate)).add(0,inTime);
                                        }
                                    }

                                    if (workTime.substring(11,13).compareTo("12") > 1){
                                        if (((Map) map).get(workDate) instanceof List){
                                            if ( ((List) ((Map) map).get(workDate)).size() <=0){
                                                ((List) ((Map) map).get(workDate)).add(0,null);
                                            }
                                            ((List) ((Map) map).get(workDate)).add(1,inTime);
                                        }
                                    }
                                }

                            }

                        }

                        if (!flag){
                            if (workTime.substring(11,13).compareTo("12") <= 0 ){
                                list.add(0,inTime);
                            }
                            if (workTime.substring(11,13).compareTo("12") > 1){
                                list.add(0,null);
                                list.add(1,inTime);
                            }
                            people.put(workDate,list);
                            people.put("attendanceGroup", attendanceGroup);
                            people.put("department", department);
                            people.put("position", position);
                            popleList.addAll(forAllListMap.get(key));
                            popleList.add(people);
                            forAllListMap.put(key, popleList);
                        }
                    }

                }catch (NumberFormatException e){
                    log.error("第 {} 行数据值非法", row.getRowNum());
                    e.printStackTrace();
                    continue;
                }catch(NullPointerException e){
                    log.error("第 {} 行数据值非法", row.getRowNum());
                    e.printStackTrace();
                    continue;
                }catch (Exception e){
                    e.printStackTrace();
                    continue;
                }
            }

            System.out.println("forAllListMap11="+JSONObject.toJSONString(forAllListMap));
            //遍历map,处理数据:
            //1）下午不为空，按时间算餐补
            //2）下午为空，上午不为空，5元餐补
            //3）上下午都为空，无餐补
            for (Map.Entry<String, List> people : forAllListMap.entrySet()) {
                StaffBonus staffBonus = new StaffBonus();
                //System.out.println("key:" + people.getKey());
               // System.out.println("value:" + people.getValue());
                ArrayList peopleItem = (ArrayList) people.getValue();
                Integer overtimeBonus = 0;   //加班餐补
                for (int i=0; i< peopleItem.size(); i++){
                    Map clockInMap = (Map) peopleItem.get(i);
                    for (Object clockInItem : clockInMap.entrySet()){
                        Map.Entry<String, Object> dateMap = (Map.Entry<String, Object>)clockInItem;
                        String date = dateMap.getKey();
                        if (dateMap.getKey().equals("attendanceGroup")) {
                            staffBonus.setAttendanceGroup((String) dateMap.getValue());
                            continue;
                        }
                        if (dateMap.getKey().equals("department")) {
                            staffBonus.setDepartment((String) dateMap.getValue());
                            continue;
                        }
                        if (dateMap.getKey().equals("position")) {
                            staffBonus.setPosition((String) dateMap.getValue());
                            continue;
                        }
                        ArrayList clockIn = (ArrayList)dateMap.getValue();
                        //System.out.println("date:" + date);
                       // System.out.println("clockin:" + clockIn);
                        //判断是否加班
                        if (clockIn.size() == 2 && clockIn.get(1) != null){
                            String getOffTime = (String) clockIn.get(1);
                            int increBonus = getincreBonus(getOffTime,date);
                            overtimeBonus = overtimeBonus + increBonus;
                        }
                    }
                }
                staffBonus.setName(people.getKey());
                staffBonus.setAttendanceDays(peopleItem.size());
                staffBonus.setDailyBonus(30);
                staffBonus.setAttendance(peopleItem.size() * 30);   //餐补:出勤*30
                staffBonus.setOvertimeBonus(overtimeBonus); //加班餐补
                staffBonus.setLate(lateMap.get(people.getKey()) == null ? 0 : lateMap.get(people.getKey()) * 5); //迟到扣除=迟到次数*5
                staffBonus.setTotalBonus(staffBonus.getAttendance() + staffBonus.getOvertimeBonus() - staffBonus.getLate());   //应得餐补 出勤正常餐补 + 加班餐补 - 迟到扣除
                staffBonus.setMonth(month);
                staffBonusList.add(staffBonus);
            }

            log.info("staffBonusList={}",JSONObject.toJSONString(staffBonusList));
        }  catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != wk) {
                try {
                    wk.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        try {
            fileService.saveStaffBouns(staffBonusList);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private int getincreBonus(String getOffTime,String date) {
        if (getOffTime.substring(11,13).compareTo("20") == 0){   //加班费10元
            return 10;
        }
        if (getOffTime.substring(11,13).compareTo("21") == 0){   //加班费20元
            return 20;
        }
        if (getOffTime.substring(11,13).compareTo("22") >= 0 || getOffTime.substring(8,10).compareTo(date.substring(6,8)) > 0){   //加班费30元(包含跨夜)
            return 30;
        }
        return 0;
    }

    @ApiOperation(value = "解析excel计算员工调休", notes = "解析excel计算员工调休")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "入参", required = true, dataType = "MultipartFile", paramType = "body")})
    @ApiResponses({@ApiResponse(code = 0000, response = ResponseEntity.class, message = "员工调休详情")})
    @PostMapping("/cal_rest")
    public ResponseEntity<?> calRest(@RequestParam(value = "file") MultipartFile file) {
        try {
            List<OriginalRecord> originalRecords = ImportExcelUtil.importExcel(file);
            fileService.calRest(originalRecords);
        } catch (Exception e) {
            log.error("解析excel计算员工调休失败:{}", e.getMessage(), e);
            throw new ServiceException("解析excel计算员工调休失败");
        }
        return GenericDataResponse.ok();
    }

}
